
#include <iostream>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include <cuda_runtime.h>
#include "Draw.h"

#define ABS(a)		(((a) < 0) ? -(a) : (a))

// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h) {
    // Evita a divisao por zero
    if (h == 0) h = 1;

    // Especifica as dimensões da Viewport
    glViewport(0, 0, w, h);

    // Inicializa o sistema de coordenadas
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Estabelece a janela de seleção (left, right, bottom, top)
    if (w <= h)
        gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f/**h/w*/);
    else
        gluOrtho2D(0.0f, 1.0f/**w/h*/, 0.0f, 1.0f);
}

void display(void) {

    // Limpa a janela de visualização com a cor de fundo especificada
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if (mostraEixo) {
        desenhaEixos();
    }

    if (mostraGrid) {
        desenhaGrid();
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    if (VBO_Ativo == true) {
        glEnableClientState(GL_VERTEX_ARRAY);
        // Especifica que a cor corrente é vermelha
        //         R     G     B
        glColor3f(0.0f, 0.6f, 1.0f);
        glBindBuffer(GL_ARRAY_BUFFER, positionsVBO);
        glVertexPointer(3, GL_FLOAT, 0, 0);
        glDrawArrays(GL_POINTS, 0, totalParticulas);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDisableClientState(GL_VERTEX_ARRAY);
    } else {
        glEnableClientState(GL_VERTEX_ARRAY);
        // Especifica que a cor corrente é vermelha
        //         R     G     B
        glColor3f(0.0f, 0.6f, 1.0f);
        glBindBuffer(GL_ARRAY_BUFFER, positionsVBO2);
        glVertexPointer(3, GL_FLOAT, 0, 0);
        glDrawArrays(GL_POINTS, 0, totalParticulas);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDisableClientState(GL_VERTEX_ARRAY);
    }

    if (mostraVetores) {
        desenhaVetores();
    }

    if (mostraPressao) {
        desenhaVetoresPressao();
    }
    if (mostraViscosidade) {
        desenhaVetoresViscosidade();
    }
    if(mostraAceleracao){
        desenhaVetoresAceleracao();
    }

    // Executa os comandos OpenGL
    glutSwapBuffers();

}

void desenhaEixos() {
    glBegin(GL_LINES);
    glColor3f(1.0, 0.0, 0.0);
    glVertex3f(1.0, 0.002, 0.0);
    glVertex3f(0.0, 0.002, 0.0);
    glVertex3f(1.0, 0.001, 0.0);
    glVertex3f(0.0, 0.001, 0.0);

    glColor3f(0.0, 1.0, 0.0);
    glVertex3f(0.001, 1.0, 0.0);
    glVertex3f(0.001, 0.0, 0.0);
    glVertex3f(0.000, 1.0, 0.0);
    glVertex3f(0.000, 0.0, 0.0);

    glEnd();
}

void desenhaGrid() {

    float posicaoI = YmaxGrid, posicaoJ = XminGrid;

    glBegin(GL_LINES);

    glColor3f(1.0, 0.4, 0.0);
    for (int i = 0; i <= resolucaoGridY; i++) {
        glVertex3f(XminGrid, posicaoI, 0.0);
        glVertex3f(XmaxGrid, posicaoI, 0.0);
        posicaoI = posicaoI - deltaYGrid;
    }
    for (int i = 0; i <= resolucaoGridX; i++) {
        glVertex3f(posicaoJ, YmaxGrid, 0.0);
        glVertex3f(posicaoJ, YminGrid, 0.0);
        posicaoJ = posicaoJ + deltaXGrid;
    }

    glEnd();
}

void desenhaVetoresAceleracao(){
    glBegin(GL_LINES);

    glColor3f(1.0, 0.0, 0.0);
    for (int i = 0; i <= totalParticulas; i++) {
        float Ex, Ey, PontoX, PontoY;
        if (forcaAceleracaoVetor[i].x != 0) {
            Ex = deltaXGrid / (5 * forcaAceleracaoVetor[i].x);
        } else {
            Ex = 0;
        }
        if (forcaAceleracaoVetor[i].y != 0) {
            Ey = deltaYGrid / (5 * forcaAceleracaoVetor[i].y);
        } else {
            Ey = 0;
        }
        PontoX = ABS(Ex) * forcaAceleracaoVetor[i].x;
        PontoY = ABS(Ey) * forcaAceleracaoVetor[i].y;
        glVertex3f(posicoesParticulasT2[i].x, posicoesParticulasT2[i].y, 0.0);
        glVertex3f(posicoesParticulasT2[i].x + PontoX,
                posicoesParticulasT2[i].y + PontoY,
                0.0);
    }
    glEnd();

}

void desenhaVetores(){
    glBegin(GL_LINES);
    glColor3f(1.0, 1.0, 0.0);
    for (int i = 0; i <= totalParticulas; i++) {
        float diferencaX = (posicoesParticulasT2[i].x - posicoesParticulasT[i].x);
        float diferencaY = (posicoesParticulasT2[i].y - posicoesParticulasT[i].y);
        float Ex, Ey, PontoX, PontoY;
        if (diferencaX != 0) {
            Ex = deltaXPart / (5 * diferencaX);
        } else {
            Ex = 0;
        }
        if (diferencaY != 0) {
            Ey = deltaYPart / (5 * diferencaY);
        } else {
            Ey = 0;
        }
        PontoX = ABS(Ex) * diferencaX;
        PontoY = ABS(Ey) * diferencaY;
        glVertex3f(posicoesParticulasT[i].x, posicoesParticulasT[i].y, 0.0);
        glVertex3f(posicoesParticulasT[i].x + PontoX,
                posicoesParticulasT[i].y + PontoY,
                0.0);
    }
    glEnd();
}

void desenhaVetoresPressao(){
    glBegin(GL_LINES);
    glColor3f(1.0, 1.0, 1.0);
    for (int i = 0; i <= totalParticulas; i++) {
        float Ex, Ey, PontoX, PontoY;
        if (forcaPressaoVetor[i].x != 0) {
            Ex = deltaXPart / (5 * forcaPressaoVetor[i].x);
        } else {
            Ex = 0;
        }
        if (forcaPressaoVetor[i].y != 0) {
            Ey = deltaYPart / (5 * forcaPressaoVetor[i].y);
        } else {
            Ey = 0;
        }
        PontoX = ABS(Ex) * forcaPressaoVetor[i].x;
        PontoY = ABS(Ey) * forcaPressaoVetor[i].y;
        glVertex3f(posicoesParticulasT[i].x, posicoesParticulasT[i].y, 0.0);
        glVertex3f(posicoesParticulasT[i].x + PontoX,
                posicoesParticulasT[i].y + PontoY,
                0.0);
    }
    glEnd();
}

void desenhaVetoresViscosidade(){
    glBegin(GL_LINES);
    glColor3f(1.0, 0.6, 0.0);
    for (int i = 0; i <= totalParticulas; i++) {
        float Ex, Ey, PontoX, PontoY;
        if (forcaPressaoVetor[i].x != 0) {
            Ex = deltaXPart / (5 * forcaViscosidadeVetor[i].x);
        } else {
            Ex = 0;
        }
        if (forcaPressaoVetor[i].y != 0) {
            Ey = deltaYPart / (5 * forcaViscosidadeVetor[i].y);
        } else {
            Ey = 0;
        }
        PontoX = ABS(Ex) * forcaViscosidadeVetor[i].x;
        PontoY = ABS(Ey) * forcaViscosidadeVetor[i].y;
        glVertex3f(posicoesParticulasT[i].x, posicoesParticulasT[i].y, 0.0);
        glVertex3f(posicoesParticulasT[i].x + PontoX,
                posicoesParticulasT[i].y + PontoY,
                0.0);
    }
    glEnd();
}